﻿namespace FFF.Test
{
    using System;
    using System.Collections.Generic;
    using System.IdentityModel.Tokens.Jwt;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    using System.Web;
    using Abp.Application.Services;
    using Abp.Dependency;
    using Abp.Extensions;
    using Abp.Runtime.Caching;
    using Abp.UI;
    using Abp.Web.Models;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Controllers;
    using Microsoft.AspNetCore.Mvc.Filters;
    using FFF.Test.Controllers;
    using FFF.Test.Util.Consts;

    /// <summary>
    /// 过滤的filter
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true)]
    public sealed class YdmMyAuthorityFilterAttribute : Attribute, IAuthorizationFilter, ITransientDependency
    {
        /// <summary>
        /// 登录的地址
        /// </summary>
        public string LoginPath { get; set; } = "/Home/Login";

        /// <summary>
        /// 缓存服务
        /// </summary>
        private readonly ICacheManager _cacheManager;

        /// <summary>
        /// Initializes a new instance of the <see cref="YdmMyAuthorityFilterAttribute"/> class.
        /// 默认返回的界面地址
        /// </summary>
        /// <param name="cacheManager">缓存对象</param>
        public YdmMyAuthorityFilterAttribute(ICacheManager cacheManager)
        {
            this._cacheManager = cacheManager;
        }

        /// <summary>
        /// 权限的校验
        /// </summary>
        /// <param name="context">请求上下文</param>
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

            if (controllerActionDescriptor != null)
            {
                bool isPage = this.IsPageRequest(context.HttpContext);

                var isDefined = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(inherit: true)
                    .Any(a => a.GetType().Equals(typeof(AllowAnonymousAttribute)));
                if (isDefined)
                {
                    return;
                }
                else
                {
                    isDefined = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
                   .Any(a => a.GetType().Equals(typeof(AllowAnonymousAttribute)));
                }

                if (isDefined)
                {
                    return;
                }

                // 如果有微信的
                var wxAttr = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes(inherit: true).OfType<WxAuthorAttribute>().FirstOrDefault();
                if (wxAttr == null)
                {
                    wxAttr = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true).OfType<WxAuthorAttribute>().FirstOrDefault();
                }

                if (wxAttr != null)
                {
                    var wxUserInfo = context.HttpContext.Session.GetWxUserInfo();
                    if (wxUserInfo == null)
                    {
                        string path = context.HttpContext.Request.Path.Value;
                        string strUrl = $"{wxAttr.LoginPath}?redirct={HttpUtility.UrlEncode(path)}";
                        context.Result = new RedirectResult(strUrl);
                        return;
                    }
                    else
                    {
                        return;
                    }
                }

                var userInfo = context.HttpContext.Session.GetUserInfo();
                if (isPage)
                {
                    Action reditAction = () =>
                    {
                        string path = context.HttpContext.Request.Path.Value;
                        string strUrl = $"{this.LoginPath}?redirct={HttpUtility.UrlEncode(path)}";
                        context.Result = new RedirectResult(strUrl);
                    };
                    if (userInfo == null)
                    {
                        reditAction();
                    }
                }
                else
                {
                    var noAuthorReslt = new JsonResult(new { __abp = true, success = false, error = new { message = "你没有权限" } });
                    if (userInfo == null)
                    {
                        context.Result = noAuthorReslt;
                    }
                    else if (userInfo.UserIsAdmin != 1)
                    {
                        var ydmAuthorAttr = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true).OfType<YdmApiAuthorAttribute>().FirstOrDefault();
                        if (ydmAuthorAttr != null)
                        {
                            // 这里只验证登录
                            if (ydmAuthorAttr.FunctionCode.IsNullOrEmpty() && ydmAuthorAttr.ActionCode.IsNullOrEmpty())
                            {
                                return;
                            }
                            else
                            {
                                // 构造多个权限点的验证
                                string[] functionCodes = ydmAuthorAttr.FunctionCode.Split("|");
                                string[] actionCodes = ydmAuthorAttr.ActionCode.Split("|");
                                for (int i = 0; i < functionCodes.Length; i++)
                                {
                                    if (userInfo.Action2Users.Any(x => x.FunctionCode == functionCodes[i] && x.ActionCode == actionCodes[i]))
                                    {
                                        return;
                                    }
                                }

                                context.Result = noAuthorReslt;
                            }
                        }
                    }
                }
            }
        }

        private bool IsPageRequest(HttpContext context)
        {
            string header = context.Request.Headers["Accept"];
            if (header == null)
            {
                return false;
            }
            else
            {
                return header.Contains("text/html");
            }
        }

    }
}